package Managers
{
	import Utils.SoundObject;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundLoaderContext;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;
	
	/**
	 * Manages all of the one off sounds in the game (no music)
	 */
	public class SoundManager extends EventDispatcher
	{
		private static var soundManagerInstance:SoundManager;
		private static var allowInstantiation:Boolean = new Boolean(false);
		
		/* List of all sounds loaded in the game */
		private var bMute:Boolean;
		private var soundTransformer:SoundTransform;
		private var soundDictionary:Dictionary = new Dictionary();
		private var sounds:Array = new Array();
		private var soundChannel:SoundChannel;
		private var effectsChannel:SoundChannel = new SoundChannel();
		private var pausePosition:Number = 0;
		
		public static function get Instance():SoundManager
		{
			if (soundManagerInstance == null)
			{
				allowInstantiation = true;
				soundManagerInstance = new SoundManager();
				allowInstantiation = false;
			}
			return soundManagerInstance;
		}
		
		public function SoundManager():void
		{
			super(null);
			if (!allowInstantiation)
			{
				return;
			}
			this.soundChannel= new SoundChannel();
			this.soundTransformer = new SoundTransform(1.0, 0);
			this.bMute = false;
		}
		
		public function ToggleMute():void
		{
			bMute = !bMute;
		}
		
		public function isMute():Boolean
		{
			return bMute;
		}
		
		/**
		 * Plays a preloaded sound
		 * @param       soundName File name of the sound to play
		 * @param       numLoops The number of time to loop the sound
		 * @return If the sound was played or not
		 */
		public function PlaySound(Name:String, numLoops:int=0):Boolean
		{
			if (this.soundDictionary[Name])
			{
				var chan:SoundChannel = this.soundDictionary[Name].sound.play(0, numLoops, this.soundTransformer);
				//trace(chan);
				/*effectsChannel.addEventListener(Event.SOUND_COMPLETE, this.onPlayComplete);
				*/return true;
			}	
			return false;
		}
		
		public function StopMusic():Boolean
		{
			if(soundChannel != null)
			{
				soundChannel.stop();
			}
			return false;
		}
		
		public function ResetPausePosition():void
		{
			pausePosition = 0;
		}
		
		public function PauseMusic():Boolean
		{
			if(soundChannel != null)
			{
				pausePosition = soundChannel.position;
			}
			return StopMusic();
		}
		
		public function PlayMusic(name:String):Boolean
		{
			var sound:SoundObject = this.soundDictionary[name];
			if(this.soundDictionary[name])
			{
				soundChannel = sound.sound.play(pausePosition, int.MAX_VALUE, this.soundTransformer);
				sound.paused = false;
				return true;
			}
			return false;
		}
				
		private function onSoundFailedToLoad(Event:IOErrorEvent):void
		{
			trace("onSoundLoaded **FAILED** ");
		}
		
		private function onPlayComplete(event:Event):void
		{
			//trace("lol?");
			effectsChannel.removeEventListener(Event.SOUND_COMPLETE, onPlayComplete);
			dispatchEvent(new Event("FINISHED"));
		}
		
		private function onSoundLoaded(event:Event):void
		{
			var localSound:Sound = event.target as Sound;
			localSound.removeEventListener(Event.COMPLETE, this.onSoundLoaded);
			localSound.removeEventListener(IOErrorEvent.IO_ERROR, this.onSoundFailedToLoad);
			var url:String = localSound.url;
			var soundName:String = url.substr(Math.max(url.lastIndexOf("/"),url.lastIndexOf("\\")) + 1, url.length);
			for (var i:int = 0; i <this.sounds.length; i++)
			{
				if (this.sounds[i].name == soundName) return;
			}
			var soundObject:SoundObject = new SoundObject(soundName, localSound, url);
			this.soundDictionary[soundName] = soundObject;
			this.sounds.push(soundObject);
		}
		
		/**
		 * Attempt to load a sound into the sound pool
		 * @param       soundName File of the sound to attempt to load
		 */
		public function LoadSound(soundName:String):void
		{
			var tempSound:Sound = new Sound();
			tempSound.addEventListener(Event.COMPLETE, this.onSoundLoaded);
			tempSound.addEventListener(IOErrorEvent.IO_ERROR, this.onSoundFailedToLoad);
			tempSound.load(new URLRequest("Data/Sounds/" + soundName));
		}
		
		public function Update(deltaTime:int):void
		{
			//Needed to update this.updateTimeTally
		}
		
		public function Destroy():void
		{
			//Cleanup all sounds
		}
	}

}